library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ──────────────────────────────────────────────────────── tidyverse 1.3.1 ──
✔ ggplot2 3.3.6     ✔ purrr   0.3.4
✔ tibble  3.1.7     ✔ dplyr   1.0.9
✔ tidyr   1.2.0     ✔ stringr 1.4.0
✔ readr   2.1.2     ✔ forcats 0.5.1
── Conflicts ─────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
library(scales)

Attaching package: ‘scales’

The following object is masked from ‘package:purrr’:

    discard

The following object is masked from ‘package:readr’:

    col_factor
library(plotly)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio

Attaching package: ‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout
library(lubridate)

Attaching package: ‘lubridate’

The following objects are masked from ‘package:base’:

    date, intersect, setdiff, union
library(sf)
Linking to GEOS 3.9.1, GDAL 3.4.3, PROJ 7.2.1; sf_use_s2() is TRUE
library(zoo)

Attaching package: ‘zoo’

The following objects are masked from ‘package:base’:

    as.Date, as.Date.numeric

Covid Tab

#load in beds and add year column
beds <- read_csv("raw_data/non_covid_raw_data/beds_by_nhs_board_of_treatment_and_specialty.csv") %>% janitor::clean_names()
Warning: One or more parsing issues, see `problems()` for detailsRows: 30458 Columns: 20── Column specification ─────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (10): Quarter, QuarterQF, HB, HBQF, Location, LocationQF, Specialty, SpecialtyQF, Special...
dbl  (5): AllStaffedBeddays, TotalOccupiedBeddays, AverageAvailableStaffedBeds, AverageOccupi...
lgl  (5): AllStaffedBeddaysQF, TotalOccupiedBeddaysQF, AverageAvailableStaffedBedsQF, Average...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
beds <- beds %>% 
mutate(quarter_date = yq(quarter),
       year = year(quarter_date), 
       .after = quarter)

beds %>% 
write_csv("clean_data/non_covid_data/beds.csv")
# bed percentage availablity for "all acute"
# Will need to add filter for year based on user input
beds_plotly <- beds %>%
  filter(specialty_name == "All Acute") %>% 
  group_by(quarter, specialty_name) %>%
  summarise(mean_perc_occ = mean(percentage_occupancy)) %>% 
  ggplot(aes(x = quarter, y = mean_perc_occ))+
  geom_line(aes(colour = specialty_name, group = specialty_name))+
  geom_point(aes(
    text = paste0("Occupancy:",round(mean_perc_occ, digits = 2)," %\n", quarter)),
    size = 0.5)+
  theme(axis.text.x = element_text(angle = 90, hjust = 1))+
  labs(title = "Mean bed availability for all Acute Patients",
       x = "\nYear and Quarter",
       y = "Average Percentage Occupancy")
`summarise()` has grouped output by 'quarter'. You can override using the `.groups` argument.Warning: Ignoring unknown aesthetics: text
ggplotly(beds_plotly, tooltip = "text") %>% 
  config(displayModeBar = FALSE) %>% 
  layout(hoverlabel=list(bgcolor="white"))
NA
NA

Scotland Shapefile

ae_wait_times wrangling

ae_wait_times <- read_csv("raw_data/non_covid_raw_data/monthly_ae_waitingtimes_202206.csv") %>% janitor::clean_names()
Rows: 15837 Columns: 25── Column specification ─────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (13): Country, HBT, TreatmentLocation, DepartmentType, NumberOfAttendancesEpisodeQF, Numb...
dbl (12): Month, NumberOfAttendancesAggregate, NumberOfAttendancesEpisode, NumberMeetingTarge...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#make a date and year column with the first date of every month
ae_wait_times <- ae_wait_times %>% 
  mutate(date = ym(month), .after = month,
         year = year(date))

#make a percent column with percent of patients meeting the 4hr target time
ae_wait_times <- ae_wait_times %>% 
  mutate(percent_4hr_target_achieved = (number_meeting_target_aggregate/number_of_attendances_aggregate)*100)

ae_wait_times %>% 
write_csv("clean_data/non_covid_data/ae_wait_times.csv")
#write in the target data for the shapefile colours
target_2007 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = 
              round(mean(percent_4hr_target_achieved, na.rm = TRUE), digits = 2)) %>% 
  filter(year == 2007) %>% 
  rename(ae_target_2007 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2007)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
  

target_2008 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = 
              round(mean(percent_4hr_target_achieved, na.rm = TRUE), digits = 2)) %>%
  filter(year == 2008) %>% 
  rename(ae_target_2008 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2008)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2009 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = 
              round(mean(percent_4hr_target_achieved, na.rm = TRUE), digits = 2)) %>% 
  filter(year == 2009) %>% 
  rename(ae_target_2009 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2009)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2010 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = 
              round(mean(percent_4hr_target_achieved, na.rm = TRUE), digits = 2)) %>% 
  filter(year == 2010) %>% 
  rename(ae_target_2010 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2010)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2011 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = 
              round(mean(percent_4hr_target_achieved, na.rm = TRUE), digits = 2)) %>% 
  filter(year == 2011) %>% 
  rename(ae_target_2011 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2011)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2012 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = 
              round(mean(percent_4hr_target_achieved, na.rm = TRUE), digits = 2)) %>% 
  filter(year == 2012) %>% 
  rename(ae_target_2012 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2012)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2013 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = 
              round(mean(percent_4hr_target_achieved, na.rm = TRUE), digits = 2)) %>% 
  filter(year == 2013) %>% 
  rename(ae_target_2013 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2013)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2014 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved =
              round(mean(percent_4hr_target_achieved, na.rm = TRUE), digits = 2)) %>% 
  filter(year == 2014) %>% 
  rename(ae_target_2014 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2014)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2015 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = 
              round(mean(percent_4hr_target_achieved, na.rm = TRUE), digits = 2)) %>% 
  filter(year == 2015) %>% 
  rename(ae_target_2015 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2015)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2016 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = 
              round(mean(percent_4hr_target_achieved, na.rm = TRUE), digits = 2)) %>% 
  filter(year == 2016) %>% 
  rename(ae_target_2016 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2016)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2017 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = 
              round(mean(percent_4hr_target_achieved, na.rm = TRUE), digits = 2)) %>% 
  filter(year == 2017) %>% 
  rename(ae_target_2017 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2017)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2018 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = 
              round(mean(percent_4hr_target_achieved, na.rm = TRUE), digits = 2)) %>% 
  filter(year == 2018) %>% 
  rename(ae_target_2018 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2018)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2019 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = 
              round(mean(percent_4hr_target_achieved, na.rm = TRUE), digits = 2)) %>% 
  filter(year == 2019) %>% 
  rename(ae_target_2019 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2019)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2020 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = 
              round(mean(percent_4hr_target_achieved, na.rm = TRUE), digits = 2)) %>% 
  filter(year == 2020) %>% 
  rename(ae_target_2020 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2020)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2021 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = 
              round(mean(percent_4hr_target_achieved, na.rm = TRUE), digits = 2)) %>% 
  filter(year == 2021) %>% 
  rename(ae_target_2021 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2021)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
  

shape file wrangling

#scotland_smaller$Shape_Area <- as.character(scotland_smaller$Shape_Area)
st_write(scotland_smaller, "clean_data/shapefile/scotland_smaller.gpkg", append = FALSE) 
Warning: Dropping column(s) centres of class(es) sfc_POINT;sfc
Deleting layer `scotland_smaller' using driver `GPKG'
Writing layer `scotland_smaller' to data source 
  `clean_data/shapefile/scotland_smaller.gpkg' using driver `GPKG'
Writing 14 features with 21 fields and geometry type Multi Polygon.

SIMD graph

simd <- read_csv("raw_data/non_covid_raw_data/inpatient_and_daycase_by_nhs_board_of_treatment_and_simd.csv") %>% janitor::clean_names()
Rows: 40821 Columns: 18── Column specification ─────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (11): Quarter, QuarterQF, HB, HBQF, Location, LocationQF, AdmissionType, AdmissionTypeQF,...
dbl  (7): SIMD, Episodes, LengthOfEpisode, AverageLengthOfEpisode, Stays, LengthOfStay, Avera...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
simd <- simd %>% 
mutate(quarter_date = yq(quarter),
       year = year(quarter_date), 
       .after = quarter)

simd %>% 
write_csv("clean_data/non_covid_data/simd.csv")
# average episodes by SIMD value
# currently unfiltered for health board or admission type etc
simd_plotly <- simd %>% 
  drop_na(simd) %>%
  mutate(simd = as.factor(simd)) %>% # gives each simd a separate colour
  group_by(quarter, simd) %>% 
  summarise(avg_episodes = mean(episodes, na.rm = TRUE)) %>% 
  ggplot(aes(x = quarter, y = avg_episodes, group = simd))+
  geom_line(aes(colour = simd))+
  geom_point(size = 0.5)+
  scale_y_continuous(labels = scales::comma)+
  labs(title = "Average Hospital Episodes by SIMD Deprevation score\n",
       x = "\nYear and Quarter",
       y = "Average Episodes\n")+
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))
`summarise()` has grouped output by 'quarter'. You can override using the `.groups` argument.
ggplotly(simd_plotly) %>% 
  config(displayModeBar = FALSE)

Age Graph

age_sex <- read_csv("raw_data/non_covid_raw_data/inpatient_and_daycase_by_nhs_board_of_treatment_age_and_sex.csv") %>% janitor::clean_names()
Rows: 129393 Columns: 18── Column specification ─────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (12): Quarter, QuarterQF, HB, HBQF, Location, LocationQF, AdmissionType, AdmissionTypeQF,...
dbl  (6): Episodes, LengthOfEpisode, AverageLengthOfEpisode, Stays, LengthOfStay, AverageLeng...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
age_sex <- age_sex %>%
    mutate(quarter_date = yq(quarter),
           year = year(quarter_date),
           .after = quarter)

age_sex %>% 
  write_csv("clean_data/non_covid_data/age_sex.csv")

# Average number of episode for age groups
# currently unfiltered by department or anything else
age_plotly <- age_sex %>% 
  #filter(min_date < year & year < max_date) %>% 
  group_by(quarter, age) %>% 
  summarise(avg_episodes = mean(episodes, na.rm = TRUE)) %>% 
  ggplot(aes(x = quarter, y = avg_episodes))+
  geom_line(aes(colour = age, group = age))+ 
  geom_point(size = 0.5)+
  labs(title = "Average Hospital Episodes by Age Groups\n",
       x = "\nYear and Quarter",
       y = "Average Episodes\n")+
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))
`summarise()` has grouped output by 'quarter'. You can override using the `.groups` argument.
  
ggplotly(age_plotly) %>% 
  config(displayModeBar = FALSE)

Gender

sex_plotly <- age_sex %>% 
  group_by(quarter, sex) %>% 
  summarise(avg_length_of_episode = mean(average_length_of_episode, na.rm = TRUE)) %>% 
  ggplot(aes(x = quarter, y = avg_length_of_episode))+
  geom_line(aes(colour = sex, group = sex))+
  #geom_smooth(aes(colour = sex, group = sex), se = FALSE)+
  geom_point(size = 0.5)+
  labs(title = "Average Hospital Episodes by Gender\n",
       x = "\nYear and Quarter",
       y = "Average Episodes\n")+
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))
`summarise()` has grouped output by 'quarter'. You can override using the `.groups` argument.
  

ggplotly(sex_plotly, hovertemplate = ) %>% 
  config(displayModeBar = FALSE)

A&E Tab

ae_wait_times <- read_csv("raw_data/non_covid_raw_data/monthly_ae_waitingtimes_202206.csv") %>% janitor::clean_names()
Rows: 15837 Columns: 25── Column specification ───────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (13): Country, HBT, TreatmentLocation, DepartmentType, NumberOfAttendancesEpisodeQF, Nu...
dbl (12): Month, NumberOfAttendancesAggregate, NumberOfAttendancesEpisode, NumberMeetingTar...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#make a date and year column with the first date of every month
ae_wait_times <- ae_wait_times %>% 
  mutate(date = ym(month), .after = month,
         year = year(date))

#make a percent column with percent of patients meeting the 4hr target time
ae_wait_times <- ae_wait_times %>% 
  mutate(percent_4hr_target_achieved = (number_meeting_target_aggregate/number_of_attendances_aggregate)*100)

ae_wait_times %>% 
  write_csv("clean_data/non_covid_data/ae_wait_times.csv")
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoc2NhbGVzKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkoc2YpDQpsaWJyYXJ5KHpvbykNCmBgYA0KDQoNCg0KIyMgQ292aWQgVGFiDQpgYGB7cn0NCiNsb2FkIGluIGJlZHMgYW5kIGFkZCB5ZWFyIGNvbHVtbg0KYmVkcyA8LSByZWFkX2NzdigicmF3X2RhdGEvbm9uX2NvdmlkX3Jhd19kYXRhL2JlZHNfYnlfbmhzX2JvYXJkX29mX3RyZWF0bWVudF9hbmRfc3BlY2lhbHR5LmNzdiIpICU+JSBqYW5pdG9yOjpjbGVhbl9uYW1lcygpDQoNCmJlZHMgPC0gYmVkcyAlPiUgDQptdXRhdGUocXVhcnRlcl9kYXRlID0geXEocXVhcnRlciksDQogICAgICAgeWVhciA9IHllYXIocXVhcnRlcl9kYXRlKSwgDQogICAgICAgLmFmdGVyID0gcXVhcnRlcikNCg0KYmVkcyAlPiUgDQp3cml0ZV9jc3YoImNsZWFuX2RhdGEvbm9uX2NvdmlkX2RhdGEvYmVkcy5jc3YiKQ0KYGBgDQoNCg0KYGBge3J9DQojIGJlZCBwZXJjZW50YWdlIGF2YWlsYWJsaXR5IGZvciAiYWxsIGFjdXRlIg0KIyBXaWxsIG5lZWQgdG8gYWRkIGZpbHRlciBmb3IgeWVhciBiYXNlZCBvbiB1c2VyIGlucHV0DQpiZWRzX3Bsb3RseSA8LSBiZWRzICU+JQ0KICBmaWx0ZXIoc3BlY2lhbHR5X25hbWUgPT0gIkFsbCBBY3V0ZSIpICU+JSANCiAgZ3JvdXBfYnkocXVhcnRlciwgc3BlY2lhbHR5X25hbWUpICU+JQ0KICBzdW1tYXJpc2UobWVhbl9wZXJjX29jYyA9IG1lYW4ocGVyY2VudGFnZV9vY2N1cGFuY3kpKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IHF1YXJ0ZXIsIHkgPSBtZWFuX3BlcmNfb2NjKSkrDQogIGdlb21fbGluZShhZXMoY29sb3VyID0gc3BlY2lhbHR5X25hbWUsIGdyb3VwID0gc3BlY2lhbHR5X25hbWUpKSsNCiAgZ2VvbV9wb2ludChhZXMoDQogICAgdGV4dCA9IHBhc3RlMCgiT2NjdXBhbmN5OiIscm91bmQobWVhbl9wZXJjX29jYywgZGlnaXRzID0gMiksIiAlXG4iLCBxdWFydGVyKSksDQogICAgc2l6ZSA9IDAuNSkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSkpKw0KICBsYWJzKHRpdGxlID0gIk1lYW4gYmVkIGF2YWlsYWJpbGl0eSBmb3IgYWxsIEFjdXRlIFBhdGllbnRzIiwNCiAgICAgICB4ID0gIlxuWWVhciBhbmQgUXVhcnRlciIsDQogICAgICAgeSA9ICJBdmVyYWdlIFBlcmNlbnRhZ2UgT2NjdXBhbmN5IikNCg0KZ2dwbG90bHkoYmVkc19wbG90bHksIHRvb2x0aXAgPSAidGV4dCIpICU+JSANCiAgY29uZmlnKGRpc3BsYXlNb2RlQmFyID0gRkFMU0UpICU+JSANCiAgbGF5b3V0KGhvdmVybGFiZWw9bGlzdChiZ2NvbG9yPSJ3aGl0ZSIpKQ0KDQoNCmBgYA0KDQojIyBTY290bGFuZCBTaGFwZWZpbGUNCiMjIyMgYWVfd2FpdF90aW1lcyB3cmFuZ2xpbmcNCmBgYHtyfQ0KYWVfd2FpdF90aW1lcyA8LSByZWFkX2NzdigicmF3X2RhdGEvbm9uX2NvdmlkX3Jhd19kYXRhL21vbnRobHlfYWVfd2FpdGluZ3RpbWVzXzIwMjIwNi5jc3YiKSAlPiUgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKQ0KDQojbWFrZSBhIGRhdGUgYW5kIHllYXIgY29sdW1uIHdpdGggdGhlIGZpcnN0IGRhdGUgb2YgZXZlcnkgbW9udGgNCmFlX3dhaXRfdGltZXMgPC0gYWVfd2FpdF90aW1lcyAlPiUgDQogIG11dGF0ZShkYXRlID0geW0obW9udGgpLCAuYWZ0ZXIgPSBtb250aCwNCiAgICAgICAgIHllYXIgPSB5ZWFyKGRhdGUpKQ0KDQojbWFrZSBhIHBlcmNlbnQgY29sdW1uIHdpdGggcGVyY2VudCBvZiBwYXRpZW50cyBtZWV0aW5nIHRoZSA0aHIgdGFyZ2V0IHRpbWUNCmFlX3dhaXRfdGltZXMgPC0gYWVfd2FpdF90aW1lcyAlPiUgDQogIG11dGF0ZShwZXJjZW50XzRocl90YXJnZXRfYWNoaWV2ZWQgPSAobnVtYmVyX21lZXRpbmdfdGFyZ2V0X2FnZ3JlZ2F0ZS9udW1iZXJfb2ZfYXR0ZW5kYW5jZXNfYWdncmVnYXRlKSoxMDApDQoNCmFlX3dhaXRfdGltZXMgJT4lIA0Kd3JpdGVfY3N2KCJjbGVhbl9kYXRhL25vbl9jb3ZpZF9kYXRhL2FlX3dhaXRfdGltZXMuY3N2IikNCmBgYA0KDQoNCmBgYHtyfQ0KI3dyaXRlIGluIHRoZSB0YXJnZXQgZGF0YSBmb3IgdGhlIHNoYXBlZmlsZSBjb2xvdXJzDQp0YXJnZXRfMjAwNyA8LSBhZV93YWl0X3RpbWVzICU+JQ0KICBncm91cF9ieSh5ZWFyLCBoYnQpICU+JSANCiAgc3VtbWFyaXNlKGFlXzRocl90YXJnZXRfYWNoaWV2ZWQgPSANCiAgICAgICAgICAgICAgcm91bmQobWVhbihwZXJjZW50XzRocl90YXJnZXRfYWNoaWV2ZWQsIG5hLnJtID0gVFJVRSksIGRpZ2l0cyA9IDIpKSAlPiUgDQogIGZpbHRlcih5ZWFyID09IDIwMDcpICU+JSANCiAgcmVuYW1lKGFlX3RhcmdldF8yMDA3ID0gYWVfNGhyX3RhcmdldF9hY2hpZXZlZCkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBzZWxlY3QoaGJ0LGFlX3RhcmdldF8yMDA3KQ0KICANCg0KdGFyZ2V0XzIwMDggPC0gYWVfd2FpdF90aW1lcyAlPiUNCiAgZ3JvdXBfYnkoeWVhciwgaGJ0KSAlPiUgDQogIHN1bW1hcmlzZShhZV80aHJfdGFyZ2V0X2FjaGlldmVkID0gDQogICAgICAgICAgICAgIHJvdW5kKG1lYW4ocGVyY2VudF80aHJfdGFyZ2V0X2FjaGlldmVkLCBuYS5ybSA9IFRSVUUpLCBkaWdpdHMgPSAyKSkgJT4lDQogIGZpbHRlcih5ZWFyID09IDIwMDgpICU+JSANCiAgcmVuYW1lKGFlX3RhcmdldF8yMDA4ID0gYWVfNGhyX3RhcmdldF9hY2hpZXZlZCkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBzZWxlY3QoaGJ0LGFlX3RhcmdldF8yMDA4KQ0KDQp0YXJnZXRfMjAwOSA8LSBhZV93YWl0X3RpbWVzICU+JQ0KICBncm91cF9ieSh5ZWFyLCBoYnQpICU+JSANCiAgc3VtbWFyaXNlKGFlXzRocl90YXJnZXRfYWNoaWV2ZWQgPSANCiAgICAgICAgICAgICAgcm91bmQobWVhbihwZXJjZW50XzRocl90YXJnZXRfYWNoaWV2ZWQsIG5hLnJtID0gVFJVRSksIGRpZ2l0cyA9IDIpKSAlPiUgDQogIGZpbHRlcih5ZWFyID09IDIwMDkpICU+JSANCiAgcmVuYW1lKGFlX3RhcmdldF8yMDA5ID0gYWVfNGhyX3RhcmdldF9hY2hpZXZlZCkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBzZWxlY3QoaGJ0LGFlX3RhcmdldF8yMDA5KQ0KDQp0YXJnZXRfMjAxMCA8LSBhZV93YWl0X3RpbWVzICU+JQ0KICBncm91cF9ieSh5ZWFyLCBoYnQpICU+JSANCiAgc3VtbWFyaXNlKGFlXzRocl90YXJnZXRfYWNoaWV2ZWQgPSANCiAgICAgICAgICAgICAgcm91bmQobWVhbihwZXJjZW50XzRocl90YXJnZXRfYWNoaWV2ZWQsIG5hLnJtID0gVFJVRSksIGRpZ2l0cyA9IDIpKSAlPiUgDQogIGZpbHRlcih5ZWFyID09IDIwMTApICU+JSANCiAgcmVuYW1lKGFlX3RhcmdldF8yMDEwID0gYWVfNGhyX3RhcmdldF9hY2hpZXZlZCkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBzZWxlY3QoaGJ0LGFlX3RhcmdldF8yMDEwKQ0KDQp0YXJnZXRfMjAxMSA8LSBhZV93YWl0X3RpbWVzICU+JQ0KICBncm91cF9ieSh5ZWFyLCBoYnQpICU+JSANCiAgc3VtbWFyaXNlKGFlXzRocl90YXJnZXRfYWNoaWV2ZWQgPSANCiAgICAgICAgICAgICAgcm91bmQobWVhbihwZXJjZW50XzRocl90YXJnZXRfYWNoaWV2ZWQsIG5hLnJtID0gVFJVRSksIGRpZ2l0cyA9IDIpKSAlPiUgDQogIGZpbHRlcih5ZWFyID09IDIwMTEpICU+JSANCiAgcmVuYW1lKGFlX3RhcmdldF8yMDExID0gYWVfNGhyX3RhcmdldF9hY2hpZXZlZCkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBzZWxlY3QoaGJ0LGFlX3RhcmdldF8yMDExKQ0KDQp0YXJnZXRfMjAxMiA8LSBhZV93YWl0X3RpbWVzICU+JQ0KICBncm91cF9ieSh5ZWFyLCBoYnQpICU+JSANCiAgc3VtbWFyaXNlKGFlXzRocl90YXJnZXRfYWNoaWV2ZWQgPSANCiAgICAgICAgICAgICAgcm91bmQobWVhbihwZXJjZW50XzRocl90YXJnZXRfYWNoaWV2ZWQsIG5hLnJtID0gVFJVRSksIGRpZ2l0cyA9IDIpKSAlPiUgDQogIGZpbHRlcih5ZWFyID09IDIwMTIpICU+JSANCiAgcmVuYW1lKGFlX3RhcmdldF8yMDEyID0gYWVfNGhyX3RhcmdldF9hY2hpZXZlZCkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBzZWxlY3QoaGJ0LGFlX3RhcmdldF8yMDEyKQ0KDQp0YXJnZXRfMjAxMyA8LSBhZV93YWl0X3RpbWVzICU+JQ0KICBncm91cF9ieSh5ZWFyLCBoYnQpICU+JSANCiAgc3VtbWFyaXNlKGFlXzRocl90YXJnZXRfYWNoaWV2ZWQgPSANCiAgICAgICAgICAgICAgcm91bmQobWVhbihwZXJjZW50XzRocl90YXJnZXRfYWNoaWV2ZWQsIG5hLnJtID0gVFJVRSksIGRpZ2l0cyA9IDIpKSAlPiUgDQogIGZpbHRlcih5ZWFyID09IDIwMTMpICU+JSANCiAgcmVuYW1lKGFlX3RhcmdldF8yMDEzID0gYWVfNGhyX3RhcmdldF9hY2hpZXZlZCkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBzZWxlY3QoaGJ0LGFlX3RhcmdldF8yMDEzKQ0KDQp0YXJnZXRfMjAxNCA8LSBhZV93YWl0X3RpbWVzICU+JQ0KICBncm91cF9ieSh5ZWFyLCBoYnQpICU+JSANCiAgc3VtbWFyaXNlKGFlXzRocl90YXJnZXRfYWNoaWV2ZWQgPQ0KICAgICAgICAgICAgICByb3VuZChtZWFuKHBlcmNlbnRfNGhyX3RhcmdldF9hY2hpZXZlZCwgbmEucm0gPSBUUlVFKSwgZGlnaXRzID0gMikpICU+JSANCiAgZmlsdGVyKHllYXIgPT0gMjAxNCkgJT4lIA0KICByZW5hbWUoYWVfdGFyZ2V0XzIwMTQgPSBhZV80aHJfdGFyZ2V0X2FjaGlldmVkKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIHNlbGVjdChoYnQsYWVfdGFyZ2V0XzIwMTQpDQoNCnRhcmdldF8yMDE1IDwtIGFlX3dhaXRfdGltZXMgJT4lDQogIGdyb3VwX2J5KHllYXIsIGhidCkgJT4lIA0KICBzdW1tYXJpc2UoYWVfNGhyX3RhcmdldF9hY2hpZXZlZCA9IA0KICAgICAgICAgICAgICByb3VuZChtZWFuKHBlcmNlbnRfNGhyX3RhcmdldF9hY2hpZXZlZCwgbmEucm0gPSBUUlVFKSwgZGlnaXRzID0gMikpICU+JSANCiAgZmlsdGVyKHllYXIgPT0gMjAxNSkgJT4lIA0KICByZW5hbWUoYWVfdGFyZ2V0XzIwMTUgPSBhZV80aHJfdGFyZ2V0X2FjaGlldmVkKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIHNlbGVjdChoYnQsYWVfdGFyZ2V0XzIwMTUpDQoNCnRhcmdldF8yMDE2IDwtIGFlX3dhaXRfdGltZXMgJT4lDQogIGdyb3VwX2J5KHllYXIsIGhidCkgJT4lIA0KICBzdW1tYXJpc2UoYWVfNGhyX3RhcmdldF9hY2hpZXZlZCA9IA0KICAgICAgICAgICAgICByb3VuZChtZWFuKHBlcmNlbnRfNGhyX3RhcmdldF9hY2hpZXZlZCwgbmEucm0gPSBUUlVFKSwgZGlnaXRzID0gMikpICU+JSANCiAgZmlsdGVyKHllYXIgPT0gMjAxNikgJT4lIA0KICByZW5hbWUoYWVfdGFyZ2V0XzIwMTYgPSBhZV80aHJfdGFyZ2V0X2FjaGlldmVkKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIHNlbGVjdChoYnQsYWVfdGFyZ2V0XzIwMTYpDQoNCnRhcmdldF8yMDE3IDwtIGFlX3dhaXRfdGltZXMgJT4lDQogIGdyb3VwX2J5KHllYXIsIGhidCkgJT4lIA0KICBzdW1tYXJpc2UoYWVfNGhyX3RhcmdldF9hY2hpZXZlZCA9IA0KICAgICAgICAgICAgICByb3VuZChtZWFuKHBlcmNlbnRfNGhyX3RhcmdldF9hY2hpZXZlZCwgbmEucm0gPSBUUlVFKSwgZGlnaXRzID0gMikpICU+JSANCiAgZmlsdGVyKHllYXIgPT0gMjAxNykgJT4lIA0KICByZW5hbWUoYWVfdGFyZ2V0XzIwMTcgPSBhZV80aHJfdGFyZ2V0X2FjaGlldmVkKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIHNlbGVjdChoYnQsYWVfdGFyZ2V0XzIwMTcpDQoNCnRhcmdldF8yMDE4IDwtIGFlX3dhaXRfdGltZXMgJT4lDQogIGdyb3VwX2J5KHllYXIsIGhidCkgJT4lIA0KICBzdW1tYXJpc2UoYWVfNGhyX3RhcmdldF9hY2hpZXZlZCA9IA0KICAgICAgICAgICAgICByb3VuZChtZWFuKHBlcmNlbnRfNGhyX3RhcmdldF9hY2hpZXZlZCwgbmEucm0gPSBUUlVFKSwgZGlnaXRzID0gMikpICU+JSANCiAgZmlsdGVyKHllYXIgPT0gMjAxOCkgJT4lIA0KICByZW5hbWUoYWVfdGFyZ2V0XzIwMTggPSBhZV80aHJfdGFyZ2V0X2FjaGlldmVkKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIHNlbGVjdChoYnQsYWVfdGFyZ2V0XzIwMTgpDQoNCnRhcmdldF8yMDE5IDwtIGFlX3dhaXRfdGltZXMgJT4lDQogIGdyb3VwX2J5KHllYXIsIGhidCkgJT4lIA0KICBzdW1tYXJpc2UoYWVfNGhyX3RhcmdldF9hY2hpZXZlZCA9IA0KICAgICAgICAgICAgICByb3VuZChtZWFuKHBlcmNlbnRfNGhyX3RhcmdldF9hY2hpZXZlZCwgbmEucm0gPSBUUlVFKSwgZGlnaXRzID0gMikpICU+JSANCiAgZmlsdGVyKHllYXIgPT0gMjAxOSkgJT4lIA0KICByZW5hbWUoYWVfdGFyZ2V0XzIwMTkgPSBhZV80aHJfdGFyZ2V0X2FjaGlldmVkKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIHNlbGVjdChoYnQsYWVfdGFyZ2V0XzIwMTkpDQoNCnRhcmdldF8yMDIwIDwtIGFlX3dhaXRfdGltZXMgJT4lDQogIGdyb3VwX2J5KHllYXIsIGhidCkgJT4lIA0KICBzdW1tYXJpc2UoYWVfNGhyX3RhcmdldF9hY2hpZXZlZCA9IA0KICAgICAgICAgICAgICByb3VuZChtZWFuKHBlcmNlbnRfNGhyX3RhcmdldF9hY2hpZXZlZCwgbmEucm0gPSBUUlVFKSwgZGlnaXRzID0gMikpICU+JSANCiAgZmlsdGVyKHllYXIgPT0gMjAyMCkgJT4lIA0KICByZW5hbWUoYWVfdGFyZ2V0XzIwMjAgPSBhZV80aHJfdGFyZ2V0X2FjaGlldmVkKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIHNlbGVjdChoYnQsYWVfdGFyZ2V0XzIwMjApDQoNCnRhcmdldF8yMDIxIDwtIGFlX3dhaXRfdGltZXMgJT4lDQogIGdyb3VwX2J5KHllYXIsIGhidCkgJT4lIA0KICBzdW1tYXJpc2UoYWVfNGhyX3RhcmdldF9hY2hpZXZlZCA9IA0KICAgICAgICAgICAgICByb3VuZChtZWFuKHBlcmNlbnRfNGhyX3RhcmdldF9hY2hpZXZlZCwgbmEucm0gPSBUUlVFKSwgZGlnaXRzID0gMikpICU+JSANCiAgZmlsdGVyKHllYXIgPT0gMjAyMSkgJT4lIA0KICByZW5hbWUoYWVfdGFyZ2V0XzIwMjEgPSBhZV80aHJfdGFyZ2V0X2FjaGlldmVkKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIHNlbGVjdChoYnQsYWVfdGFyZ2V0XzIwMjEpDQogIA0KYGBgDQoNCiMjIyMgc2hhcGUgZmlsZSB3cmFuZ2xpbmcNCmBgYHtyfQ0Kc2NvdGxhbmQgPC0gc3RfcmVhZCgiLi4vU0dfTkhTX0hlYWx0aEJvYXJkc18yMDE5X3NoYXBlZmlsZS9TR19OSFNfSGVhbHRoQm9hcmRzXzIwMTkuc2hwIikNCg0KIyBtYWtlIGEgc21hbGxlciB2ZXJzaW9uIGZvciBwZXJmb3JtYW5jZSBpc3N1ZXMNCnNjb3RsYW5kX3NtYWxsZXIgPC0gc2NvdGxhbmQgJT4lIA0KICBzdF9zaW1wbGlmeShUUlVFLCBkVG9sZXJhbmNlID0gMjAwMCkNCiNmaXhlcyBwcm9ibGVtcyBjYXVzZWQgYnkgYWJvdmUgDQpzY290bGFuZF9zbWFsbGVyIDwtIHNmOjpzdF9jYXN0KHNjb3RsYW5kX3NtYWxsZXIsICJNVUxUSVBPTFlHT04iKQ0KDQojYWRkIGluIHRoZSBBJkUgNCBociB0YXJnZXQgZGF0YSBmb3IgZWFjaCB5ZWFyDQpzY290bGFuZF9zbWFsbGVyIDwtICBzY290bGFuZF9zbWFsbGVyICU+JSANCiAgbXV0YXRlKGNlbnRyZXMgPSBzdF9jZW50cm9pZChzdF9tYWtlX3ZhbGlkKGdlb21ldHJ5KSkpICU+JQ0KICAgIG11dGF0ZShsYXQgPSBzdF9jb29yZGluYXRlcyhjZW50cmVzKVssMV0sDQogICAgICAgICAgIGxvbmcgPSBzdF9jb29yZGluYXRlcyhjZW50cmVzKVssMl0sDQogICAgICAgICAgIHRhcmdldF8yMDA3ID0gdGFyZ2V0XzIwMDckYWVfdGFyZ2V0XzIwMDcsDQogICAgICAgICAgIHRhcmdldF8yMDA4ID0gdGFyZ2V0XzIwMDgkYWVfdGFyZ2V0XzIwMDgsDQogICAgICAgICAgIHRhcmdldF8yMDA5ID0gdGFyZ2V0XzIwMDkkYWVfdGFyZ2V0XzIwMDksDQogICAgICAgICAgIHRhcmdldF8yMDEwID0gdGFyZ2V0XzIwMTAkYWVfdGFyZ2V0XzIwMTAsDQogICAgICAgICAgIHRhcmdldF8yMDExID0gdGFyZ2V0XzIwMTEkYWVfdGFyZ2V0XzIwMTEsDQogICAgICAgICAgIHRhcmdldF8yMDEyID0gdGFyZ2V0XzIwMTIkYWVfdGFyZ2V0XzIwMTIsDQogICAgICAgICAgIHRhcmdldF8yMDEzID0gdGFyZ2V0XzIwMTMkYWVfdGFyZ2V0XzIwMTMsDQogICAgICAgICAgIHRhcmdldF8yMDE0ID0gdGFyZ2V0XzIwMTQkYWVfdGFyZ2V0XzIwMTQsDQogICAgICAgICAgIHRhcmdldF8yMDE1ID0gdGFyZ2V0XzIwMTUkYWVfdGFyZ2V0XzIwMTUsDQogICAgICAgICAgIHRhcmdldF8yMDE2ID0gdGFyZ2V0XzIwMTYkYWVfdGFyZ2V0XzIwMTYsDQogICAgICAgICAgIHRhcmdldF8yMDE3ID0gdGFyZ2V0XzIwMTckYWVfdGFyZ2V0XzIwMTcsDQogICAgICAgICAgIHRhcmdldF8yMDE4ID0gdGFyZ2V0XzIwMTgkYWVfdGFyZ2V0XzIwMTgsDQogICAgICAgICAgIHRhcmdldF8yMDE5ID0gdGFyZ2V0XzIwMTkkYWVfdGFyZ2V0XzIwMTksDQogICAgICAgICAgIHRhcmdldF8yMDIwID0gdGFyZ2V0XzIwMjAkYWVfdGFyZ2V0XzIwMjAsDQogICAgICAgICAgIHRhcmdldF8yMDIxID0gdGFyZ2V0XzIwMjEkYWVfdGFyZ2V0XzIwMjENCiAgICAgICAgICAgICAgICAgICkNCg0KI3Njb3RsYW5kX3NtYWxsZXIkU2hhcGVfQXJlYSA8LSBhcy5jaGFyYWN0ZXIoc2NvdGxhbmRfc21hbGxlciRTaGFwZV9BcmVhKQ0Kc3Rfd3JpdGUoc2NvdGxhbmRfc21hbGxlciwgImNsZWFuX2RhdGEvc2hhcGVmaWxlL3Njb3RsYW5kX3NtYWxsZXIuZ3BrZyIsIGFwcGVuZCA9IEZBTFNFKSANCg0KIyMgdGhlbiB0byByZS1sb2FkIGRhdGEgKGFsc28gdXNpbmcgdGhlIGRwbHlyIGxpYnJhcnkpOg0Kc2NvdGxhbmRfc21hbGxlciA8LSBzdF9yZWFkKCJjbGVhbl9kYXRhL3NoYXBlZmlsZS9zY290bGFuZF9zbWFsbGVyLmdwa2ciKSANCiAjIG11dGF0ZShTaGFwZV9BcmVhID0gYXMuaW50ZWdlcihTaGFwZV9BcmVhKSkNCg0KDQoNCiMgIyBUaGlzIHdpbGwgcmVxdWlyZSBmaWx0ZXJlZCBieSB0aGUgeWVhciBzZWxlY3RlZCBpbiB0aGUgZGFzaGJvYXJkDQojICMgQ2FuIHdlIGdldCB0aGUgYnV0dG9uIG9yIGRyb3Bkb3duIHRvIHBhc3MgZWcgInRhcmdldF8yMDE2IiB0byB0aGlzIGluIDIgcGxhY2VzPw0KIyAgbXlkYXRhMiA8LSBzdF9jb2xsZWN0aW9uX2V4dHJhY3Qoc2NvdGxhbmRfc21hbGxlciwgIlBPTFlHT04iKQ0KIyAjSSB3YXMgdGhlbiBhYmxlIHRvIHNhdmUgdGhlIG5ldyBmaWxlIHByb3Blcmx5LCBpLmUuLi4NCiMgc3Rfd3JpdGUobXlkYXRhMiwgImNsZWFuX2RhdGEvc2NvdGxhbmRfc21hbGxlci5zaHAiLCBhcHBlbmQgPSBGQUxTRSkNCiMgDQojIA0KIyBzdF93cml0ZShzY290bGFuZF9zbWFsbGVyLCAiY2xlYW5fZGF0YS9zY290bGFuZF9zbWFsbGVyLnBna2ciLCBhcHBlbmQgPSBGQUxTRSkNCiMgDQojIHNjb3RsYW5kX3NtYWxsZXIgPC0gc3RfcmVhZCgiY2xlYW5fZGF0YS9zY290bGFuZF9zbWFsbGVyLnNocCIpDQoNCnAgPC0gZ2dwbG90KHNjb3RsYW5kX3NtYWxsZXIpICsgDQogIGdlb21fc2YoYWVzKGZpbGwgPSB0YXJnZXRfMjAyMSwgDQogICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgiPGI+IiwgSEJOYW1lLCAiPC9iPlxuIiwgcm91bmQodGFyZ2V0XzIwMjEsIGRpZ2l0cyA9IDIpLCIlIiwgc2VwID0gIiIpKSkgKyANCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Mob3B0aW9uID0gInBsYXNtYSIsIG5hbWUgPSAiNEhyIEEmRSBUYXJnZXQgJSIpKw0KICB0aGVtZV92b2lkKCkrDQogIGxhYnModGl0bGUgPSAiUGVyY2VudCBvZiBBJkUgZGVwdHMgbWFraW5nIHRoZSA0aHIgdGFyZ2V0IikNCg0KcCAlPiUNCiAgZ2dwbG90bHkodG9vbHRpcCA9ICJ0ZXh0IikgJT4lDQogIHN0eWxlKGhvdmVybGFiZWwgPSBsaXN0KGJnY29sb3IgPSAid2hpdGUiKSwgaG92ZXJvbiA9ICJmaWxsIiklPiUgDQogIGNvbmZpZyhkaXNwbGF5TW9kZUJhciA9IEZBTFNFKQ0KYGBgDQoNCiMjIFNJTUQgZ3JhcGggDQoNCmBgYHtyfQ0Kc2ltZCA8LSByZWFkX2NzdigicmF3X2RhdGEvbm9uX2NvdmlkX3Jhd19kYXRhL2lucGF0aWVudF9hbmRfZGF5Y2FzZV9ieV9uaHNfYm9hcmRfb2ZfdHJlYXRtZW50X2FuZF9zaW1kLmNzdiIpICU+JSBqYW5pdG9yOjpjbGVhbl9uYW1lcygpDQoNCnNpbWQgPC0gc2ltZCAlPiUgDQptdXRhdGUocXVhcnRlcl9kYXRlID0geXEocXVhcnRlciksDQogICAgICAgeWVhciA9IHllYXIocXVhcnRlcl9kYXRlKSwgDQogICAgICAgLmFmdGVyID0gcXVhcnRlcikNCg0Kc2ltZCAlPiUgDQp3cml0ZV9jc3YoImNsZWFuX2RhdGEvbm9uX2NvdmlkX2RhdGEvc2ltZC5jc3YiKQ0KYGBgDQoNCmBgYHtyfQ0KIyBhdmVyYWdlIGVwaXNvZGVzIGJ5IFNJTUQgdmFsdWUNCiMgY3VycmVudGx5IHVuZmlsdGVyZWQgZm9yIGhlYWx0aCBib2FyZCBvciBhZG1pc3Npb24gdHlwZSBldGMNCnNpbWRfcGxvdGx5IDwtIHNpbWQgJT4lIA0KICBkcm9wX25hKHNpbWQpICU+JQ0KICBtdXRhdGUoc2ltZCA9IGFzLmZhY3RvcihzaW1kKSkgJT4lICMgZ2l2ZXMgZWFjaCBzaW1kIGEgc2VwYXJhdGUgY29sb3VyDQogIGdyb3VwX2J5KHF1YXJ0ZXIsIHNpbWQpICU+JSANCiAgc3VtbWFyaXNlKGF2Z19lcGlzb2RlcyA9IG1lYW4oZXBpc29kZXMsIG5hLnJtID0gVFJVRSkpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gcXVhcnRlciwgeSA9IGF2Z19lcGlzb2RlcywgZ3JvdXAgPSBzaW1kKSkrDQogIGdlb21fbGluZShhZXMoY29sb3VyID0gc2ltZCkpKw0KICBnZW9tX3BvaW50KHNpemUgPSAwLjUpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSkrDQogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBIb3NwaXRhbCBFcGlzb2RlcyBieSBTSU1EIERlcHJldmF0aW9uIHNjb3JlXG4iLA0KICAgICAgIHggPSAiXG5ZZWFyIGFuZCBRdWFydGVyIiwNCiAgICAgICB5ID0gIkF2ZXJhZ2UgRXBpc29kZXNcbiIpKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQoNCmdncGxvdGx5KHNpbWRfcGxvdGx5KSAlPiUgDQogIGNvbmZpZyhkaXNwbGF5TW9kZUJhciA9IEZBTFNFKQ0KYGBgDQoNCiMjIEFnZSBHcmFwaA0KDQpgYGB7cn0NCmFnZV9zZXggPC0gcmVhZF9jc3YoInJhd19kYXRhL25vbl9jb3ZpZF9yYXdfZGF0YS9pbnBhdGllbnRfYW5kX2RheWNhc2VfYnlfbmhzX2JvYXJkX29mX3RyZWF0bWVudF9hZ2VfYW5kX3NleC5jc3YiKSAlPiUgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKQ0KDQphZ2Vfc2V4IDwtIGFnZV9zZXggJT4lDQogICAgbXV0YXRlKHF1YXJ0ZXJfZGF0ZSA9IHlxKHF1YXJ0ZXIpLA0KICAgICAgICAgICB5ZWFyID0geWVhcihxdWFydGVyX2RhdGUpLA0KICAgICAgICAgICAuYWZ0ZXIgPSBxdWFydGVyKQ0KDQphZ2Vfc2V4ICU+JSANCiAgd3JpdGVfY3N2KCJjbGVhbl9kYXRhL25vbl9jb3ZpZF9kYXRhL2FnZV9zZXguY3N2IikNCmBgYA0KDQpgYGB7cn0NCg0KIyBBdmVyYWdlIG51bWJlciBvZiBlcGlzb2RlIGZvciBhZ2UgZ3JvdXBzDQojIGN1cnJlbnRseSB1bmZpbHRlcmVkIGJ5IGRlcGFydG1lbnQgb3IgYW55dGhpbmcgZWxzZQ0KYWdlX3Bsb3RseSA8LSBhZ2Vfc2V4ICU+JSANCiAgI2ZpbHRlcihtaW5fZGF0ZSA8IHllYXIgJiB5ZWFyIDwgbWF4X2RhdGUpICU+JSANCiAgZ3JvdXBfYnkocXVhcnRlciwgYWdlKSAlPiUgDQogIHN1bW1hcmlzZShhdmdfZXBpc29kZXMgPSBtZWFuKGVwaXNvZGVzLCBuYS5ybSA9IFRSVUUpKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IHF1YXJ0ZXIsIHkgPSBhdmdfZXBpc29kZXMpKSsNCiAgZ2VvbV9saW5lKGFlcyhjb2xvdXIgPSBhZ2UsIGdyb3VwID0gYWdlKSkrIA0KICBnZW9tX3BvaW50KHNpemUgPSAwLjUpKw0KICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgSG9zcGl0YWwgRXBpc29kZXMgYnkgQWdlIEdyb3Vwc1xuIiwNCiAgICAgICB4ID0gIlxuWWVhciBhbmQgUXVhcnRlciIsDQogICAgICAgeSA9ICJBdmVyYWdlIEVwaXNvZGVzXG4iKSsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KICANCmdncGxvdGx5KGFnZV9wbG90bHkpICU+JSANCiAgY29uZmlnKGRpc3BsYXlNb2RlQmFyID0gRkFMU0UpDQpgYGANCg0KIyMgR2VuZGVyDQoNCmBgYHtyfQ0Kc2V4X3Bsb3RseSA8LSBhZ2Vfc2V4ICU+JSANCiAgZ3JvdXBfYnkocXVhcnRlciwgc2V4KSAlPiUgDQogIHN1bW1hcmlzZShhdmdfbGVuZ3RoX29mX2VwaXNvZGUgPSBtZWFuKGF2ZXJhZ2VfbGVuZ3RoX29mX2VwaXNvZGUsIG5hLnJtID0gVFJVRSkpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gcXVhcnRlciwgeSA9IGF2Z19sZW5ndGhfb2ZfZXBpc29kZSkpKw0KICBnZW9tX2xpbmUoYWVzKGNvbG91ciA9IHNleCwgZ3JvdXAgPSBzZXgpKSsNCiAgI2dlb21fc21vb3RoKGFlcyhjb2xvdXIgPSBzZXgsIGdyb3VwID0gc2V4KSwgc2UgPSBGQUxTRSkrDQogIGdlb21fcG9pbnQoc2l6ZSA9IDAuNSkrDQogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBIb3NwaXRhbCBFcGlzb2RlcyBieSBHZW5kZXJcbiIsDQogICAgICAgeCA9ICJcblllYXIgYW5kIFF1YXJ0ZXIiLA0KICAgICAgIHkgPSAiQXZlcmFnZSBFcGlzb2Rlc1xuIikrDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCiAgDQoNCmdncGxvdGx5KHNleF9wbG90bHksIGhvdmVydGVtcGxhdGUgPSApICU+JSANCiAgY29uZmlnKGRpc3BsYXlNb2RlQmFyID0gRkFMU0UpDQpgYGANCiMjIEEmRSBUYWINCmBgYHtyfQ0KI1RIRSBBJkUgV0FJIFRUSU1FUyBJUyBIQU5ETEVEIEFCT1ZFIElOIFRIRSBTSEFQRUZJTEUgV1JBTkdMSU5HIFNFQ1RJT04gQUhISEhIIElNIFNIT1VUSU5HDQoNCiMgYWVfd2FpdF90aW1lcyA8LSByZWFkX2NzdigicmF3X2RhdGEvbm9uX2NvdmlkX3Jhd19kYXRhL21vbnRobHlfYWVfd2FpdGluZ3RpbWVzXzIwMjIwNi5jc3YiKSAlPiUgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKQ0KIyANCiMgI21ha2UgYSBkYXRlIGFuZCB5ZWFyIGNvbHVtbiB3aXRoIHRoZSBmaXJzdCBkYXRlIG9mIGV2ZXJ5IG1vbnRoDQojIGFlX3dhaXRfdGltZXMgPC0gYWVfd2FpdF90aW1lcyAlPiUgDQojICAgbXV0YXRlKGRhdGUgPSB5bShtb250aCksIC5hZnRlciA9IG1vbnRoLA0KIyAgICAgICAgICB5ZWFyID0geWVhcihkYXRlKSkNCiMgDQojICNtYWtlIGEgcGVyY2VudCBjb2x1bW4gd2l0aCBwZXJjZW50IG9mIHBhdGllbnRzIG1lZXRpbmcgdGhlIDRociB0YXJnZXQgdGltZQ0KIyBhZV93YWl0X3RpbWVzIDwtIGFlX3dhaXRfdGltZXMgJT4lIA0KIyAgIG11dGF0ZShwZXJjZW50XzRocl90YXJnZXRfYWNoaWV2ZWQgPSAobnVtYmVyX21lZXRpbmdfdGFyZ2V0X2FnZ3JlZ2F0ZS9udW1iZXJfb2ZfYXR0ZW5kYW5jZXNfYWdncmVnYXRlKSoxMDApDQojIA0KIyBhZV93YWl0X3RpbWVzICU+JSANCiMgICB3cml0ZV9jc3YoImNsZWFuX2RhdGEvbm9uX2NvdmlkX2RhdGEvYWVfd2FpdF90aW1lcy5jc3YiKQ0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeShyZ2RhbCkNCmxpYnJhcnkobGVhZmxldCkNCnNjb3RsYW5kX3NtYWxsZXIgPC0gIHJlYWRPR1IoIi4uL1NHX05IU19IZWFsdGhCb2FyZHNfMjAxOV9zaGFwZWZpbGUvIixsYXllciA9ICJTR19OSFNfSGVhbHRoQm9hcmRzXzIwMTkiKQ0Kc2hhcGVEYXRhIDwtIHNwVHJhbnNmb3JtKHNjb3RsYW5kX3NtYWxsZXIsIENSUygiK3Byb2o9bG9uZ2xhdCArZWxscHM9R1JTODAiKSkNCg0KeCA9IHN0X3JlYWQoImNsZWFuX2RhdGEvc2hhcGVmaWxlL3Njb3RsYW5kX3NtYWxsZXIuZ3BrZyIpICANCg0Kc2NvdGxhbmQgPC0gIHNjb3RsYW5kICU+JSANCiAgbXV0YXRlKGNlbnRyZXMgPSBzdF9jZW50cm9pZChzdF9tYWtlX3ZhbGlkKGdlb21ldHJ5KSkpICU+JQ0KICAgIG11dGF0ZShsYXQgPSBzdF9jb29yZGluYXRlcyhjZW50cmVzKVssMV0sDQogICAgICAgICAgIGxvbmcgPSBzdF9jb29yZGluYXRlcyhjZW50cmVzKVssMl0pDQoNCg0Kc2NvdGxhbmQgPC0gc3RfdHJhbnNmb3JtKHgsICcrcHJvaj1sb25nbGF0ICtkYXR1bT1XR1M4NCcpDQoNCnBhbCA8LSBjb2xvck51bWVyaWMoInZpcmlkaXMiLCBOVUxMKQ0KDQptIDwtIGxlYWZsZXQoKSANCm0gJT4lIGFkZFRpbGVzKCkgJT4lIA0KICBhZGRQb2x5Z29ucyhkYXRhPXNjb3RsYW5kLA0KICAgICAgICAgICAgICBzbW9vdGhGYWN0b3IgPSAwLjMsIA0KICAgICAgICAgICAgICBmaWxsT3BhY2l0eSA9IDEsDQogICAgICAgICAgICAgIGZpbGxDb2xvciA9IH5wYWwodGFyZ2V0XzIwMDcpLA0KICAgICAgICAgICAgICBsYWJlbCA9IH5wYXN0ZTAoIEhCTmFtZSwiOiAiLCB0YXJnZXRfMjAwNyksDQogICAgICAgICAgICAgIHdlaWdodCA9IDEsIA0KICAgICAgICAgICAgICBoaWdobGlnaHRPcHRpb25zID0gaGlnaGxpZ2h0T3B0aW9ucyhjb2xvciA9ICJ3aGl0ZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2VpZ2h0ID0gMiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmluZ1RvRnJvbnQgPSBUUlVFKSkgJT4lIA0KICBhZGRMZWdlbmQocGFsID0gcGFsLCB2YWx1ZXMgPSBzY290bGFuZCR0YXJnZXRfMjAwNywgb3BhY2l0eSA9IDEsICkNCmBgYA0KDQo=